<?php
/**
+-----------------------------------------------------------------------------------------------
* GouGuOPEN [ 左手研发，右手开源，未来可期！]
+-----------------------------------------------------------------------------------------------
* @Copyright (c) 2021~2024 http://www.gouguoa.com All rights reserved.
+-----------------------------------------------------------------------------------------------
* @Licensed 勾股OA，开源且可免费使用，但并不是自由软件，未经授权许可不能去除勾股OA的相关版权信息
+-----------------------------------------------------------------------------------------------
* @Author 勾股工作室 <hdm58@qq.com>
+-----------------------------------------------------------------------------------------------
*/
namespace app\lawcase\model;

use think\Model;
use think\facade\Db;

class Party extends Model
{
    protected $dateFormat = false; // 禁用日期格式自动转换
    
    /**
     * 获取当事人列表
     * @param array $where 查询条件
     * @param array $param 分页参数
     * @return array
     */
    public function getList($where = [], $param = [])
    {
        $rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
        $order = empty($param['order']) ? 'id desc' : $param['order'];
        
        try {
            $list = $this->alias('p')
                ->join('region r1', 'p.pid = r1.id', 'LEFT')
                ->join('region r2', 'p.cid = r2.id', 'LEFT')
                ->join('region r3', 'p.did = r3.id', 'LEFT')
                ->where($where)
                ->where('p.delete_time', 0)
                ->field('p.*, r1.name as province_name, r2.name as city_name, r3.name as district_name')
                ->order($order)
                ->paginate(['list_rows' => $rows, 'query' => $param])
                ->each(function($item) {
                    // 获取关联案件数量
                    $item->case_count = Db::name('lawcase_party')
                        ->where(['party_id' => $item->id, 'delete_time' => 0])
                        ->count();
                    
                    return $item;
                });
                
            return [
                'code' => 0,
                'msg' => 'success',
                'count' => $list->total(),
                'data' => $list->items()
            ];
        } catch (\Exception $e) {
            return ['code' => 1, 'data' => [], 'msg' => $e->getMessage()];
        }
    }
    
    /**
     * 添加当事人
     * @param array $data 当事人数据
     * @return int|string 新增ID
     */
    public function add($data)
    {
        try {
            $data['create_time'] = time();
            $id = $this->strict(false)->insertGetId($data);
            add_log('add', $id, $data);
            return $id;
        } catch (\Exception $e) {
            throw new \Exception('添加当事人失败：' . $e->getMessage());
        }
    }
    
    /**
     * 编辑当事人
     * @param array $data 当事人数据
     * @return bool
     */
    public function edit($data)
    {
        try {
            $data['update_time'] = time();
            $res = $this->strict(false)->where('id', $data['id'])->update($data);
            add_log('edit', $data['id'], $data);
            return $res !== false;
        } catch (\Exception $e) {
            throw new \Exception('编辑当事人失败：' . $e->getMessage());
        }
    }
    
    /**
     * 删除当事人
     * @param int|array $ids 当事人ID或ID数组
     * @param bool $force 是否强制删除（忽略关联案件）
     * @return bool
     */
    public function remove($ids, $force = false)
    {
        try {
            // 转换为数组
            $ids = is_array($ids) ? $ids : [$ids];
            
            if (!$force) {
                // 检查是否被案件引用
                $hasCases = Db::name('lawcase_party')
                    ->where('party_id', 'in', $ids)
                    ->where('delete_time', 0)
                    ->count();
                
                if ($hasCases > 0) {
                    throw new \Exception('当事人已关联案件，无法删除');
                }
            }
            
            // 执行软删除
            $this->where('id', 'in', $ids)->update(['delete_time' => time()]);
            
            // 记录日志
            foreach ($ids as $id) {
                add_log('delete', $id);
            }
            
            return true;
        } catch (\Exception $e) {
            throw new \Exception('删除当事人失败：' . $e->getMessage());
        }
    }
    
    /**
     * 获取当事人详情
     * @param int $id 当事人ID
     * @return array|null
     */
    public function getDetail($id)
    {
        $detail = $this->alias('p')
        ->join('region r1', 'p.pid = r1.id', 'LEFT')
        ->join('region r2', 'p.cid = r2.id', 'LEFT')
        ->join('region r3', 'p.did = r3.id', 'LEFT')
        ->where(['p.id' => $id, 'p.delete_time' => 0])
        ->field('p.*, r1.name as province_name, r2.name as city_name, r3.name as district_name')
        ->find();
        if (!$detail) {
            return null;
        }
        
        $detail = $detail->toArray();
        // 确保party_type有默认值
        $detail['party_type'] = $detail['party_type'] ?? 1;
        
        // 获取关联案件
        $cases = Db::name('lawcase_party')
            ->alias('cp')
            ->join('lawcase lc', 'cp.case_id = lc.id')
            ->where(['cp.party_id' => $id, 'cp.delete_time' => 0, 'lc.delete_time' => 0])
            ->field('cp.*, cp.case_id, lc.case_code')
            ->select()
            ->each(function($item) {
                // 格式化诉讼地位
                $item['party_type_text'] = $this->getPartyTypeText($item['party_type'] ?? 1);
                return $item;
            })
            ->toArray();
            
        // 计算关联案件数
        $detail['case_count'] = count($cases);
        $detail['cases'] = $cases;
        
        return $detail;
    }
    
    /**
     * 检查证件号码是否已存在
     * @param string $idNumber 证件号码
     * @param int $excludeId 排除的ID (编辑时使用)
     * @return bool
     */
    public function idNumberExists($idNumber, $excludeId = 0)
    {
        $query = $this->where([
            ['id_number', '=', $idNumber],
            ['delete_time', '=', 0]
        ]);
        
        if ($excludeId > 0) {
            $query->where('id', '<>', $excludeId);
        }
        
        return $query->count() > 0;
    }
    
    /**
     * 根据证件号码查询当事人
     * @param string $idNumber 证件号码
     * @return array|null
     */
    public function getByIdNumber($idNumber)
    {
        return $this->where([
            ['id_number', '=', $idNumber],
            ['delete_time', '=', 0]
        ])->find();
    }
    
    /**
     * 获取当事人选择器数据
     * @param int $type 当事人类型：1个人 2企业，0表示全部
     * @return array
     */
    public function getSelectData($type = 0)
    {
        $query = $this->where('delete_time', 0);
        
        if ($type > 0) {
            $query->where('type', $type);
        }
        
        return $query->field('id, name, type, id_number, phone')
            ->order('id desc')
            ->select()
            ->each(function($item) {
                return $item;
            })
            ->toArray();
    }
    
    /**
     * 批量添加当事人
     * @param array $dataList 当事人数据列表
     * @return array 添加结果，包含成功数量和失败数量
     */
    public function batchAdd($dataList)
    {
        $success = 0;
        $fail = 0;
        $time = time();
        
        // 开启事务
        Db::startTrans();
        
        try {
            foreach ($dataList as $data) {
                // 检查证件号码是否已存在
                $exists = $this->idNumberExists($data['id_number']);
                
                if ($exists) {
                    $fail++;
                    continue;
                }
                
                $data['create_time'] = $time;
                $id = $this->strict(false)->insertGetId($data);
                
                if ($id) {
                    $success++;
                    add_log('add', $id, $data);
                } else {
                    $fail++;
                }
            }
            
            // 提交事务
            Db::commit();
            
            return ['success' => $success, 'fail' => $fail];
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            throw new \Exception('批量添加当事人失败：' . $e->getMessage());
        }
    }
    
    /**
     * 搜索当事人
     * @param string $keyword 关键词
     * @param int $limit 返回数量限制
     * @return array
     */
    public function search($keyword, $limit = 10)
    {
        return $this->where('delete_time', 0)
            ->where(function($query) use ($keyword) {
                $query->where('name', 'like', "%{$keyword}%")
                    ->whereOr('id_number', 'like', "%{$keyword}%")
                    ->whereOr('phone', 'like', "%{$keyword}%");
            })
            ->field('id, name, type, id_number, phone')
            ->limit($limit)
            ->select()
            ->each(function($item) {
                $item['type_text'] = $this->getTypeText($item['type']);
                return $item;
            })
            ->toArray();
    }
    
    /**
     * 获取当事人角色类型文本
     * @param int $roleType 角色类型值
     * @return string
     */
    protected function getRoleTypeText($roleType)
    {
        $types = [
            1 => '委托人',
            2 => '对方当事人',
            3 => '第三人'
        ];
        
        return isset($types[$roleType]) ? $types[$roleType] : '未知角色';
    }
    
    /**
     * 获取诉讼地位文本
     * @param int $partyType 诉讼地位值
     * @return string
     */
    protected function getPartyTypeText($partyType)
    {
        $types = [
            0 => '未知',
            1 => '原告',
            2 => '被告',
            3 => '第三人',
            4 => '上诉人',
            5 => '被上诉人',
            6 => '再审申请人',
            7 => '再审被申请人',
            8 => '申请执行人',
            9 => '被申请执行人'
        ];
        
        return isset($types[$partyType]) ? $types[$partyType] : '未知地位';
    }
    
    /**
     * 验证身份证号码格式
     * @param string $idNumber 身份证号码
     * @return bool
     */
    public static function validateIdNumber($idNumber)
    {
        // 15位身份证号码
        if (strlen($idNumber) == 15) {
            return preg_match('/^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$/', $idNumber);
        }
        
        // 18位身份证号码
        if (strlen($idNumber) == 18) {
            return preg_match('/^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/', $idNumber);
        }
        
        return false;
    }
    
    /**
     * 验证统一社会信用代码格式
     * @param string $code 统一社会信用代码
     * @return bool
     */
    public static function validateSocialCreditCode($code)
    {
        return preg_match('/^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/', $code);
    }
}